package com.iceframework.core.quartz.utils;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iceframework.core.quartz.job.HttpClientQuartzJob;

/**
 * 
 * 任务调度公共类
 * 
 * @author Palo
 *
 */
public class QuartzUtils {

	private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
	private static Logger log = LoggerFactory.getLogger(QuartzUtils.class);// 日志

	/**
	 * 第一种：按秒定时 单位：秒
	 * 
	 * @param jobName
	 * @param triggerName
	 * @param jobClass
	 * @param seconds
	 * @throws SchedulerException
	 */
	public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<? extends Job> jobClass, int seconds) throws SchedulerException {
		log.info("启动定时任务：" + jobName);
		// 创建一个SchedulerFactory工厂实例
		SchedulerFactory sf = new StdSchedulerFactory();
		// 通过SchedulerFactory构建Scheduler对象
		Scheduler sche = sf.getScheduler();
		// 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
		// 构建一个触发器，规定触发的规则
		Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
				.withIdentity(triggerName, triggerGroupName)// 给触发器起一个名字和组名
				.startNow()// 立即执行
				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds)// 时间间隔
						.repeatForever()// 一直执行
				).build();// 产生触发器
		// 向Scheduler中添加job任务和trigger触发器
		sche.scheduleJob(jobDetail, trigger);
		// 启动
		sche.start();
	}

	/**
	 * 第二种：按表达式定时 CronScheduleBuilder.cronSchedule("0 17 1 * * ?")
	 * CronTrigger使用cron表达式来设置触发时间。CronTrigger创建方式：
	 * CronScheduleBuilder.cronSchedule("0 53 19 ? * *") [[秒] [分] [小时] [日] [月] [周]
	 * [年] 当前为每天下午7点53执行
	 * 
	 * @param jobName
	 * @param triggerName
	 * @param jobClass
	 * @param expression
	 * @throws SchedulerException
	 */
	public static void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<? extends Job> jobClass, String expression) throws SchedulerException {
		log.info("启动定时任务：" + jobName);
		// 创建一个SchedulerFactory工厂实例
		SchedulerFactory sf = new StdSchedulerFactory();
		// 通过SchedulerFactory构建Scheduler对象
		Scheduler sche = sf.getScheduler();
		// 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
		// 构建一个触发器，规定触发的规则
		Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
				.withIdentity(triggerName, triggerGroupName)// 给触发器起一个名字和组名
				.startNow()// 立即执行
				.withSchedule(CronScheduleBuilder.cronSchedule(expression)).build();// 产生触发器
		// 向Scheduler中添加job任务和trigger触发器
		sche.scheduleJob(jobDetail, trigger);
		// 启动
		sche.start();
	}

	/**
	 * 第一种：按秒定时 单位：秒
	 * 
	 * @param jobName
	 * @param triggerName
	 * @param jobClass
	 * @param seconds
	 * @throws SchedulerException
	 */
	public static void addHttpClientJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String url, int seconds) throws SchedulerException {
		log.info("启动定时任务：" + jobName);
		// 创建一个SchedulerFactory工厂实例
		SchedulerFactory sf = new StdSchedulerFactory();
		// 通过SchedulerFactory构建Scheduler对象
		Scheduler sche = sf.getScheduler();
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("url", url);
		// 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
		JobDetail jobDetail = JobBuilder.newJob(HttpClientQuartzJob.class).withIdentity(jobName, jobGroupName).setJobData(jobDataMap).build();
		// 构建一个触发器，规定触发的规则
		Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
				.withIdentity(triggerName, triggerGroupName)// 给触发器起一个名字和组名
				.startNow()// 立即执行
				.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(seconds)// 时间间隔
						.repeatForever()// 一直执行
				).build();// 产生触发器
		// 向Scheduler中添加job任务和trigger触发器
		sche.scheduleJob(jobDetail, trigger);
		// 启动
		sche.start();
	}

	/**
	 * 第二种：按表达式定时 CronScheduleBuilder.cronSchedule("0 17 1 * * ?")
	 * CronTrigger使用cron表达式来设置触发时间。CronTrigger创建方式：
	 * CronScheduleBuilder.cronSchedule("0 53 19 ? * *") [[秒] [分] [小时] [日] [月] [周]
	 * [年] 当前为每天下午7点53执行
	 * 
	 * @param jobName
	 * @param triggerName
	 * @param jobClass
	 * @param expression
	 * @throws SchedulerException
	 */
	public static void addHttpClientJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, String url, String expression) throws SchedulerException {
		log.info("启动定时任务：" + jobName);
		// 创建一个SchedulerFactory工厂实例
		SchedulerFactory sf = new StdSchedulerFactory();
		// 通过SchedulerFactory构建Scheduler对象
		Scheduler sche = sf.getScheduler();
		JobDataMap jobDataMap = new JobDataMap();
		jobDataMap.put("url", url);
		// 用于描叙Job实现类及其他的一些静态信息，构建一个作业实例
		JobDetail jobDetail = JobBuilder.newJob(HttpClientQuartzJob.class).withIdentity(jobName, jobGroupName).setJobData(jobDataMap).build();
		// 构建一个触发器，规定触发的规则
		Trigger trigger = TriggerBuilder.newTrigger()// 创建一个新的TriggerBuilder来规范一个触发器
				.withIdentity(triggerName, triggerGroupName)// 给触发器起一个名字和组名
				.startNow()// 立即执行
				.withSchedule(CronScheduleBuilder.cronSchedule(expression)).build();// 产生触发器
		// 向Scheduler中添加job任务和trigger触发器
		sche.scheduleJob(jobDetail, trigger);
		// 启动
		sche.start();
	}

	/**
	 * @Description: 修改一个任务的触发时间
	 * 
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName      触发器名
	 * @param triggerGroupName 触发器组名
	 * @param cron             时间设置，参考quartz说明文档
	 */
	public static void modifyJobTime(String triggerName, String triggerGroupName, String cron) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldTime = trigger.getCronExpression();
			if (!oldTime.equalsIgnoreCase(cron)) {
				/** 方式一 ：调用 rescheduleJob 开始 */
				// 触发器
				TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
				// 触发器名,触发器组
				triggerBuilder.withIdentity(triggerName, triggerGroupName);
				triggerBuilder.startNow();
				// 触发器时间设定
				triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
				// 创建Trigger对象
				trigger = (CronTrigger) triggerBuilder.build();
				// 方式一 ：修改一个任务的触发时间
				sched.rescheduleJob(triggerKey, trigger);
				/** 方式一 ：调用 rescheduleJob 结束 */

				/** 方式二：先删除，然后在创建一个新的Job */
				// JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName,
				// jobGroupName));
				// Class<? extends Job> jobClass = jobDetail.getJobClass();
				// removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
				// addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
				/** 方式二 ：先删除，然后在创建一个新的Job */
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static boolean existJob(String triggerName, String triggerGroupName) throws SchedulerException {
		Scheduler sched = schedulerFactory.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
		CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
		if (trigger == null) {
			return false;
		}
		return true;
	}

	/**
	 * @Description: 移除一个任务
	 * 
	 * @param jobName
	 * @param jobGroupName
	 * @param triggerName
	 * @param triggerGroupName
	 */
	public static void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
		try {
			Scheduler sched = schedulerFactory.getScheduler();

			TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);

			sched.pauseTrigger(triggerKey);// 停止触发器
			sched.unscheduleJob(triggerKey);// 移除触发器
			sched.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 启动所有定时任务
	 */
	public static void startJobs() {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			sched.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 关闭所有定时任务
	 */
	public static void shutdownJobs() {
		try {
			Scheduler sched = schedulerFactory.getScheduler();
			if (!sched.isShutdown()) {
				sched.shutdown();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}